
import * as React from 'react';
import { Switch, Text, Button, View } from 'react-native';
import { StatusBar } from "react-native-bars";
import { RNCamera, FaceDetector, CameraType, FlashMode, AutoFocus, WhiteBalance, CustomWhiteBalance, RecordResponse } from 'react-native-camera';
import {
    StyleSheet,
    TouchableOpacity,
    TouchableWithoutFeedback,
    Dimensions,
} from 'react-native';

const flashModeOrder = {
    off: 'on',
    on: 'auto',
    auto: 'torch',
    torch: 'off',
};

const wbOrder = {
    auto: 'sunny',
    sunny: 'cloudy',
    cloudy: 'shadow',
    shadow: 'fluorescent',
    fluorescent: 'incandescent',
    incandescent: 'auto',
};

const landmarkSize = 2;



export function BarExample() {

    const [backColor, setBackColor] = React.useState("red");
    const [videoType, setType] = React.useState<keyof CameraType>('back');
    const [flash, setFlash] = React.useState<keyof FlashMode>("on");
    const [zoom, setZoom] = React.useState(0);
    const [autoFocus, setAutoFocus] = React.useState<keyof AutoFocus>("off");
    const [depth, setdepth] = React.useState(0.5);
    const [whiteBalance, setWhiteBalance] = React.useState<keyof WhiteBalance | CustomWhiteBalance>("sunny");
    const [ratio, setratio] = React.useState("16:9");
    const [autoFocusPoint, setAutoFocusPoint] = React.useState({
        normalized: { x: 0.5, y: 0.5 }, // normalized values required for autoFocusPointOfInterest
        drawRectPosition: {
            x: Dimensions.get('window').width * 0.5 - 32,
            y: Dimensions.get('window').height * 0.5 - 32,
        }
    });
    const [recordOptions, setRecordOptions] = React.useState({
        mute: false,
        maxDuration: 5,
        // quality: RNCamera.Constants.VideoQuality['288p'],
    });
    const [faces, setFaces] = React.useState([]);
    const [textBlocks, setTextBlocks] = React.useState([]);
    const [barcodes, setBarcodes] = React.useState([]);
    const [isRecording, setIsRecording] = React.useState(false);
    const [canDetectFaces, setCanDetectFaces] = React.useState(false);
    const [canDetectText, setCanDetectText] = React.useState(false);
    const [canDetectBarcode, setCanDetectBarcode] = React.useState(false);
    const [preview, setPreview] = React.useState(true);
    const drawFocusRingPosition = {
        top: autoFocusPoint.drawRectPosition.y - 32,
        left: autoFocusPoint.drawRectPosition.x - 32,
    };

    const facesDetected = ({ faces }) => {
        if (canDetectFaces) {
            setFaces(faces)
        }
    };

    const onCameraReady = () => {
        console.log("rn cameraReady 2222")
    }

    const textRecognized = object => {
        if (canDetectText) {
            const { textBlocks } = object;
            setTextBlocks(textBlocks);
        }

    };

    const barcodeRecognized = ({ barcodes }) => {
        if (canDetectBarcode) {
            setBarcodes(barcodes)
        }
    };

    function touchToFocus(event) {
        const { pageX, pageY } = event.nativeEvent;
        const screenWidth = Dimensions.get('window').width;
        const screenHeight = Dimensions.get('window').height;
        const isPortrait = screenHeight > screenWidth;

        let x = pageX / screenWidth;
        let y = pageY / screenHeight;
        // Coordinate transform for portrait. See autoFocusPointOfInterest in docs for more info
        if (isPortrait) {
            x = pageY / screenHeight;
            y = -(pageX / screenWidth) + 1;
        }

        setAutoFocusPoint(
            {
                normalized: { x, y },
                drawRectPosition: { x: pageX, y: pageY },
            },
        );
    }

    const toggle = value => () => {
        // this.setState(prevState => ({ [value]: !prevState[value] }));
    }

    function toggleFacing() {
        setType(
            videoType === 'back' ? 'front' : 'back'
        );
    }

    function toggleFlash() {
        // setFlash(flashModeOrder[flash]);
    }

    function toggleWB() {
        // setWhiteBalance(
        //     wbOrder[whiteBalance]
        // );
    }

    const stopVideo = async () => {
        //todo 这个感觉调到了camera的方法
        await this.camera.stopRecording();
        setIsRecording(false);
    };

    function renderRecBtn() {
        return <Text style={styles.flipText}> REC </Text>;
    }

    function renderStopRecBtn() {
        return <Text style={styles.flipText}> ☕ </Text>;
    }

    const takeVideo = async () => {
        const { isRecording } = this.state;
        if (this.camera && !isRecording) {
            try {
                const promise = this.camera.recordAsync(this.state.recordOptions);

                if (promise) {
                    setIsRecording(true);
                    const data = await promise;
                    console.warn('takeVideo', data);
                }
            } catch (e) {
                console.error(e);
            }
        }
    };


    const renderRecording = () => {
        const backgroundColor = isRecording ? 'white' : 'darkred';
        const action = isRecording ? stopVideo : takeVideo;
        const button = isRecording ? renderStopRecBtn() : renderRecBtn();

        return (
            <TouchableOpacity
                style={[
                    styles.flipButton,
                    {
                        flex: 0.3,
                        alignSelf: 'flex-end',
                        backgroundColor,
                    },
                ]}
                onPress={() => action()}
            >
                {button}
            </TouchableOpacity>
        );
    };

    function zoomOut() {
        setZoom(zoom - 0.1 < 0 ? 0 : zoom - 0.1,
        );
    }

    function zoomIn() {
        setZoom(
            zoom + 0.1 > 1 ? 1 : zoom + 0.1,
        );
    }

    function toggleFocus() {
        setAutoFocus(
            autoFocus === 'on' ? 'off' : 'on',
        );
    }

    const takePicture = async function () {
        if (this.camera) {
            const data = await this.camera.takePictureAsync();
            console.warn('takePicture ', data);
        }
    };

    const renderFaces = () => (
        <View style={styles.facesContainer} pointerEvents="none">
            {faces.map(this.renderFace)}
        </View>
    );

    const renderLandmarks = () => (
        <View style={styles.facesContainer} pointerEvents="none">
            {faces.map(this.renderLandmarksOfFace)}
        </View>
    );

    const renderTextBlocks = () => (
        <View style={styles.facesContainer} pointerEvents="none">
            {textBlocks.map(this.renderTextBlock)}
        </View>
    );

    const renderTextBlock = ({ bounds, value }) => (
        <React.Fragment key={value + bounds.origin.x}>
            <Text style={[styles.textBlock, { left: bounds.origin.x, top: bounds.origin.y }]}>
                {value}
            </Text>
            <View
                style={[
                    styles.text,
                    {
                        ...bounds.size,
                        left: bounds.origin.x,
                        top: bounds.origin.y,
                    },
                ]}
            />
        </React.Fragment>
    );

    const renderBarcodes = () => (
        <View style={styles.facesContainer} pointerEvents="none">
            {barcodes.map(this.renderBarcode)}
        </View>
    );


    return (
            <View style={{ backgroundColor: backColor }}>
                <View style={[styles.button, styles.margin20]}


                    onTouchEnd={() => {
                        console.log("rn click")
                        FaceDetector.detectFacesAsync("test", {})
                        const options = {
                            quality: 0.5,
                            base64: true,
                            width: 300,
                            height: 300,
                        };

                        // const result = this.camera.takePictureAsync(options);
                        this.camera.takePictureAsync(options).then((photoResult) => {
                            console.log("takepicture result:" + photoResult?.path)
                        });

                        this.camera.getAvailablePictureSizes();
                        this.camera.getSupportedRatiosAsync();
                        this.camera.getSupportedPreviewFpsRange();
                        this.camera.getCameraIdsAsync().then((data)=>{
                            for (let i = 0; i < data.length; i++) {
                                console.log("example rn:id:"+ data[i].id + "--type:" + data[i].type);
                              }
                        });
                        setBackColor(backColor == 'red' ? 'green' : 'red')
                    }
                    }>
                    <Text style={styles.buttonText}>测试FaceDetector</Text>
                </View>
                <View style={[styles.button, styles.margin20]}
                    onTouchEnd={() => {
                        console.log("rn click")
                        //纯rn方法，这个方法调用的方法会调到native，rn侧需要harmony逻辑适配下
                        this.camera.refreshAuthorizationStatus();
                    }
                    }>
                    <Text style={styles.buttonText}>refreshAuthorizationStatus</Text>
                </View>
                <View style={[styles.button, styles.margin20]}
                    onTouchEnd={() => {
                        console.log("rn isRecording")
                        this.camera.isRecording().then((isRecording) => {
                            console.log("rn back isRecording:" + isRecording)
                        });
                        console.log("rn stoprecord")
                        this.camera.stopRecording();
                    }
                    }>
                    <Text style={styles.buttonText}>isRecording & stopRecord</Text>
                </View>

                <View style={[styles.button, styles.margin20]}
                    onTouchEnd={() => {
                        console.log("rn pauseRecording")
                        this.camera.pauseRecording();
                    }
                    }>
                    <Text style={styles.buttonText}>pauseRecording</Text>

                </View>

                <View style={[styles.button, styles.margin20]}
                    onTouchEnd={() => {
                        console.log("rn resumeRecording")
                        this.camera.resumeRecording();
                    }
                    }>
                    <Text style={styles.buttonText}>resumeRecording</Text>

                </View>

                <View style={[styles.button, styles.margin20]}
                    onTouchEnd={() => {
                        console.log("rn pausePreview")
                        this.camera.pausePreview();
                        setPreview(false);
                    }
                    }>
                    <Text style={styles.buttonText}>pausePreview</Text>

                </View>

                <View style={[styles.button, styles.margin20]}
                    onTouchEnd={() => {
                        console.log("rn resumePreview")
                        this.camera.resumePreview();
                        setPreview(true);
                    }
                    }>
                    <Text style={styles.buttonText}>resumePreview</Text>

                </View>

                <View style={[styles.button, styles.margin20]}
                    onTouchEnd={() => {
                        console.log("rn recordAsync")
                        const recordOptions = {
                            mute: false,
                            maxDuration: 5,
                        }
                        this.camera.recordAsync(recordOptions).then((videoResult: RecordResponse) => {
                            console.log("recordAsync result:" + videoResult.uri)
                        });;
                    }
                    }>
                    <Text style={styles.buttonText}>recordAsync</Text>

                </View>

                <RNCamera
                    ref={ref => {
                        this.camera = ref;
                    }}
                    style={{
                        backgroundColor: 'black',
                        flex: 1,
                        justifyContent: 'space-between',
                    }}
                    onTap={(point)=>{
                        console.log("onTap point.x:" + point.x)
                        console.log("onTap point.y:" + point.x)
                    }}
                    onDoubleTap={(point)=>{
                        console.log("onDoubleTap point.x:" + point.x)
                        console.log("onDoubleTap point.y:" + point.x)
                    }}
                    onMountError={(error)=>{
                        console.log("onMountError error:" + error.message)
                    }}
                    onRecordingStart={(data)=>{
                        if (data.nativeEvent) {
                            console.log("onRecordingStart :" + data.nativeEvent.uri)
                            console.log("onRecordingStart :" + data.nativeEvent.videoOrientation)
                            console.log("onRecordingStart :" + data.nativeEvent.deviceOrientation)
                        }else{
                            console.log("onRecordingStart :111")
                        }
                       
                    }}
                    onPictureTaken={()=>{
                        console.log("RN onPictureTaken")
                    }}
                   onRecordingEnd={()=>{
                    console.log("onRecordingEnd end:")
                   }}
                    type={videoType}
                    flashMode={flash}
                    autoFocus={autoFocus}
                    autoFocusPointOfInterest={autoFocusPoint.normalized}
                    zoom={zoom}
                    whiteBalance={whiteBalance}
                    ratio={ratio}
                    focusDepth={depth}
                    useNativeZoom={true}
                    exposure={1}
                
                    onBarCodeRead={()=>{

                    }}
                    videoStabilizationMode={"cinematic"}
                    defaultVideoQuality={"1080p"}
                    faceDetectionLandmarks={
                        RNCamera.Constants.FaceDetection.Landmarks
                            ? RNCamera.Constants.FaceDetection.Landmarks.all
                            : undefined
                    }
                    onCameraReady={onCameraReady}
                    onAudioConnected={()=>{
                        console.log("rn onAudioConnected")
                    }}
                    onStatusChange={(data)=>{
                        console.log("rn onStatusChange camera:" + data.cameraStatus)
                        console.log("rn onStatusChange camera:" + data.recordAudioPermissionStatus)
                    }}
                    onFacesDetected={facesDetected}
                    onTextRecognized={textRecognized}
                    onGoogleVisionBarcodesDetected={barcodeRecognized}
                >
                    <View style={StyleSheet.absoluteFill}>
                        <View style={[styles.autoFocusBox, drawFocusRingPosition]} />
                        <TouchableWithoutFeedback onPress={touchToFocus.bind(this)}>
                            <View style={{ flex: 1 }} />
                        </TouchableWithoutFeedback>
                    </View>
                    <View
                        style={{
                            flex: 0.5,
                            height: 72,
                            backgroundColor: 'transparent',
                            flexDirection: 'row',
                            justifyContent: 'space-around',
                        }}
                    >
                        <View
                            style={{
                                backgroundColor: 'transparent',
                                flexDirection: 'row',
                                justifyContent: 'space-around',
                            }}
                        >
                            <TouchableOpacity style={styles.flipButton} onPress={toggleFacing.bind(this)}>
                                <Text style={styles.flipText}> FLIP </Text>
                            </TouchableOpacity>
                            <TouchableOpacity style={styles.flipButton} onPress={toggleFlash.bind(this)}>
                                <Text style={styles.flipText}> FLASH: {flash} </Text>
                            </TouchableOpacity>
                            <TouchableOpacity style={styles.flipButton} onPress={toggleWB.bind(this)}>
                                <Text style={styles.flipText}> WB:  </Text>
                            </TouchableOpacity>
                        </View>
                        <View
                            style={{
                                backgroundColor: 'transparent',
                                flexDirection: 'row',
                                justifyContent: 'space-around',
                            }}
                        >
                            <TouchableOpacity onPress={toggle('canDetectFaces')} style={styles.flipButton}>
                                <Text style={styles.flipText}>
                                    {!canDetectFaces ? 'Detect Faces' : 'Detecting Faces'}
                                </Text>
                            </TouchableOpacity>
                            <TouchableOpacity onPress={toggle('canDetectText')} style={styles.flipButton}>
                                <Text style={styles.flipText}>
                                    {!canDetectText ? 'Detect Text' : 'Detecting Text'}
                                </Text>
                            </TouchableOpacity>
                            <TouchableOpacity onPress={toggle('canDetectBarcode')} style={styles.flipButton}>
                                <Text style={styles.flipText}>
                                    {!canDetectBarcode ? 'Detect Barcode' : 'Detecting Barcode'}
                                </Text>
                            </TouchableOpacity>
                        </View>
                    </View>

                    <View style={{ bottom: 0 }}>
                        <View
                            style={{
                                height: 20,
                                backgroundColor: 'transparent',
                                flexDirection: 'row',
                                alignSelf: 'flex-end',
                            }}
                        >
                            {/* <Slider
              style={{ width: 150, marginTop: 15, alignSelf: 'flex-end' }}
              onValueChange={this.setFocusDepth.bind(this)}
              step={0.1}
              disabled={this.state.autoFocus === 'on'}
            /> */}
                        </View>
                        <View
                            style={{
                                height: 56,
                                backgroundColor: 'transparent',
                                flexDirection: 'row',
                                alignSelf: 'flex-end',
                            }}
                        >
                            {renderRecording()}
                        </View>
                        {zoom !== 0 && (
                            <Text style={[styles.flipText, styles.zoomText]}>Zoom: {zoom}</Text>
                        )}
                        <View
                            style={{
                                height: 56,
                                backgroundColor: 'transparent',
                                flexDirection: 'row',
                                alignSelf: 'flex-end',
                            }}
                        >
                            <TouchableOpacity
                                style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
                                onPress={zoomIn.bind(this)}
                            >
                                <Text style={styles.flipText}> + </Text>
                            </TouchableOpacity>
                            <TouchableOpacity
                                style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
                                onPress={zoomOut.bind(this)}
                            >
                                <Text style={styles.flipText}> - </Text>
                            </TouchableOpacity>
                            <TouchableOpacity
                                style={[styles.flipButton, { flex: 0.25, alignSelf: 'flex-end' }]}
                                onPress={toggleFocus.bind(this)}
                            >
                                <Text style={styles.flipText}> AF : {autoFocus} </Text>
                            </TouchableOpacity>
                            <TouchableOpacity
                                style={[styles.flipButton, styles.picButton, { flex: 0.3, alignSelf: 'flex-end' }]}
                                onPress={takePicture.bind(this)}
                            >
                                <Text style={styles.flipText}> SNAP </Text>
                            </TouchableOpacity>
                        </View>
                    </View>
                    {!!canDetectFaces && renderFaces()}
                    {!!canDetectFaces && renderLandmarks()}
                    {!!canDetectText && renderTextBlocks()}
                    {!!canDetectBarcode && renderBarcodes()}
                </RNCamera>
            </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        paddingTop: 10,
        backgroundColor: '#000',
    },
    button: {
        width: 160,
        height: 36,
        backgroundColor: 'hsl(190, 50%, 70%)',
        paddingHorizontal: 16,
        paddingVertical: 8,
        borderRadius: 8,
    },
    margin20: {
        marginLeft: 20
    },
    buttonText: {
        width: '100%',
        height: '100%',
        fontWeight: 'bold',
    },
    flipButton: {
        flex: 0.3,
        height: 40,
        marginHorizontal: 2,
        marginBottom: 10,
        marginTop: 10,
        borderRadius: 8,
        borderColor: 'white',
        borderWidth: 1,
        padding: 5,
        alignItems: 'center',
        justifyContent: 'center',
    },
    autoFocusBox: {
        position: 'absolute',
        height: 64,
        width: 64,
        borderRadius: 12,
        borderWidth: 2,
        borderColor: 'white',
        opacity: 0.4,
    },
    flipText: {
        color: 'white',
        fontSize: 15,
    },
    zoomText: {
        position: 'absolute',
        bottom: 70,
        zIndex: 2,
        left: 2,
    },
    picButton: {
        backgroundColor: 'darkseagreen',
    },
    facesContainer: {
        position: 'absolute',
        bottom: 0,
        right: 0,
        left: 0,
        top: 0,
    },
    face: {
        padding: 10,
        borderWidth: 2,
        borderRadius: 2,
        position: 'absolute',
        borderColor: '#FFD700',
        justifyContent: 'center',
        backgroundColor: 'rgba(0, 0, 0, 0.5)',
    },
    landmark: {
        width: 0,
        height: 0,
        position: 'absolute',
        backgroundColor: 'red',
    },
    faceText: {
        color: '#FFD700',
        fontWeight: 'bold',
        textAlign: 'center',
        margin: 10,
        backgroundColor: 'transparent',
    },
    text: {
        padding: 10,
        borderWidth: 2,
        borderRadius: 2,
        position: 'absolute',
        borderColor: '#F00',
        justifyContent: 'center',
    },
    textBlock: {
        color: '#F00',
        position: 'absolute',
        textAlign: 'center',
        backgroundColor: 'transparent',
    },
});

export default {
    displayName: 'pull-to-refresh',
    framework: 'React',
    category: 'UI',
    title: 'pull-to-refresh',
    documentationURL: 'pull-to-refresh',
    description: '',
    examples: [
        {
            title: 'react-native-camera',
            render: function (): any {
                return <BarExample />;
            },
        },
    ],
};